#![feature(panic_info_message)]
#![no_std]
#![no_main]
use core::panic::PanicInfo;
use core::arch::global_asm;
use crate::sbi::shutdown;

#[macro_use]
mod console;
mod sbi;

global_asm!(include_str!("entry.asm"));

#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
    if let Some(location) = info.location() {
        println!(
            "Panicked at {}:{} {}",
            location.file(),
            location.line(),
            info.message().unwrap()
        );
    } else {
        println!("Panicked: {}", info.message().unwrap());
    }
    shutdown();
}

#[no_mangle]
pub fn rust_main() -> ! {
    clear_bss();
    extern "C" {
        fn stext();
        fn etext();
        fn sbss();
        fn ebss();
        fn srodata();
        fn erodata();
        fn sdata();
        fn edata();
    }
    debug!(".text [{:#x}, {:#x}]", stext as usize, etext as usize);
    debug!(".rodata [{:#x}, {:#x}]", srodata as usize, erodata as usize);
    debug!(".data [{:#x}, {:#x}]", sdata as usize, edata as usize);
    debug!(".bss [{:#x}, {:#x}]", sbss as usize, ebss as usize);
    panic!("Shutdown machine");
}

fn clear_bss() {
    extern "C" {
        fn sbss();
        fn ebss();
    }

    (sbss as usize..ebss as usize).for_each(|a| {
        unsafe { (a as *mut u8).write_volatile(0) }
    });
}
